import React from "react";
import { connect } from "react-redux";
import { deepFullCopy, messages, queryCurrencyPrecision } from "share/common";
import ResizeTable from "components/resize-table";
import { Col, Input, InputNumber, message, Popover, Row, Tag } from "antd";
import Condition from "components/condition";
import chooserData from "share/chooserData";
import Chooser from "components/chooser";
import config from "config";
import configureStore from "stores/index";
import Selector from "components/selector";
import baseService from "share/base.service";

const If = Condition.If;
const InputGroup = Input.Group;

import "styles/corporate-payment-report/pre-payment-apportion.scss";
import debounce from "lodash.debounce";

class PrePaymentApportion extends React.Component {
  constructor(props) {
    super(props);
    this.init = debounce(this.init, 300);
  }
  state = {
    columns: [
      {
        title: messages("common.sequence") /*序号*/,
        dataIndex: "index",
        stableWidth: 72,
        render: (text, record, index) => <span>{index + 1}</span>,
      },
      {
        title: messages("expense-1.key1") /*分摊项*/,
        dataIndex: "costCenterRender",
        width: 240,
        minWidth: 180,
        render: (text, record, index) => this.renderColumns(record, "costCenterRender", index),
      },
      {
        title: messages("expense-1.key198") /*分摊金额*/,
        dataIndex: "amount",
        width: 160,
        minWidth: 140,
        render: (text, record, index) => this.renderColumns(record, "amount", index),
      },
      {
        title: messages("expense-1.key199") /*分摊比例*/,
        dataIndex: "proportion",
        stableWidth: 120,
        render: (text, record, index) => this.renderColumns(record, "proportion", index),
      },
      {
        title: messages("common.operation") /*操作*/,
        dataIndex: "operate",
        minWidth: 120,
        render: (text, record, index) => this.renderColumns(record, "operate", index),
      },
    ],
    expenseApportion: [],
    defaultExpenseApportion: [],
  };

  componentDidMount() {
    const { options, readOnly } = this.props;
    const { columns } = this.state;
    // 分摊公司
    if (this.safeGet(options, "invoiceConfigOpt.enableExpenseApportionCompany")) {
      let constCenterField = columns.find((item) => item.dataIndex === "costCenterRender");
      columns.splice(columns.indexOf(constCenterField), 0, {
        title: messages("finance-9.key151") /*分摊公司*/,
        dataIndex: "companyRender",
        width: 200,
        minWidth: 180,
        render: (text, record, index) => this.renderColumns(record, "companyRender", index),
      });
      this.setState({ columns });
    }
    if (readOnly) {
      let _columns = columns.filter((item) => item.dataIndex !== "operate");
      this.setState({ columns: _columns });
    }
    this.init(this.props);
  }

  componentWillReceiveProps(nextProps) {
    this.init(nextProps);
  }

  init = (props = {}) => {
    const { apportionValue, amount } = props;
    const { expenseApportion } = this.state;
    let currencyPrecision = this.getCurrencyPrecision();
    if (!apportionValue || apportionValue.length === 0) {
      let defaultApportionmentList = [
        {
          costCenterItemDTOList: this.getDefaultCostCenterItems(),
          defaultApportion: true,
          proportion: 1,
          apportionmentCompanyName: null,
          apportionmentCompanyOID: null,
          amount,
        },
      ];
      this.props.onChange(defaultApportionmentList);
      this.setState({
        defaultExpenseApportion: defaultApportionmentList[0],
        expenseApportion: defaultApportionmentList,
      });
    } else if (!expenseApportion[0] && apportionValue && apportionValue.length > 0) {
      this.setState({
        expenseApportion: apportionValue,
        defaultExpenseApportion: apportionValue[0],
      });
    } else if (expenseApportion[0]) {
      let apportionAmountSum = 0;
      let { length } = expenseApportion;
      expenseApportion.map((item) => (apportionAmountSum += Number(item.amount)));
      apportionAmountSum = Number(apportionAmountSum.toFixed(currencyPrecision));
      expenseApportion.map((item, index) => {
        if (apportionAmountSum !== amount) {
          if (index !== length - 1) {
            item.amount = Number((amount * item.proportion).toFixed(currencyPrecision));
          } else {
            const otherApportions = expenseApportion.slice(0, index);
            let otherAmountSum = 0;
            otherApportions.map((item) => (otherAmountSum += Number(item.amount)));
            let _amount = amount - otherAmountSum;
            item.amount = _amount > 0 ? Number(_amount.toFixed(currencyPrecision)) : 0;
          }
        }
      });
      this.setState({
        expenseApportion,
        defaultExpenseApportion: expenseApportion[0],
      });
    }
  };

  // 获取默认分摊项
  getDefaultCostCenterItems = () => {
    const {
      expenseInfo: { custFormValues },
    } = this.props;
    const _custFormValues = deepFullCopy(custFormValues);
    return _custFormValues
      .filter(
        (item) =>
          ["select_department", "select_cost_center"].includes(item.messageKey) &&
          JSON.parse(item.fieldConstraint).isApportionItem
      )
      .map((item) => {
        if (item.messageKey === "select_cost_center") {
          item.costCenterOID = JSON.parse(item.dataSource).costCenterOID;
        } else {
          item.costCenterOID = "00000000-0000-0000-0000-000000000000";
        }
        return {
          fieldName: item.fieldName,
          fieldCode: item.fieldCode,
          costCenterOID: item.costCenterOID,
          costCenterItemOID: item.value,
          costCenterItemName: item.showValue,
          required: item.required,
          itemCode: item.valueCode,
          type: null,
          costCenterName: null,
          apportionItem: true,
        };
      });
  };

  // 获取币种精度
  getCurrencyPrecision = (currencyCode = this.props.currencyCode) => {
    return queryCurrencyPrecision(currencyCode);
  };

  renderColumns = (record, attr, index) => {
    const { readOnly } = this.props;
    const { defaultExpenseApportion } = this.state;
    let currencyPrecision = this.getCurrencyPrecision();
    switch (attr) {
      case "costCenterRender":
        let labels = record.apportionmentLabels || [];
        return (
          <div className="department">
            <If value={labels.length > 0}>
              {labels.map((item, i) => {
                let color = "blue";
                if (item.level === "ERROR") color = "red";
                return (
                  <Tag key={i} color={color}>
                    {item.name}
                  </Tag>
                );
              })}
            </If>
            {(defaultExpenseApportion.costCenterItemDTOList || []).map((costCenterItem, i) => {
              let isHaveItem = false;
              let costCenterItemIndex = 0;
              (record.costCenterItemDTOList || []).map((item, indexCostCenterItems) => {
                if (item.costCenterOID === costCenterItem.costCenterOID) {
                  isHaveItem = true;
                  costCenterItemIndex = indexCostCenterItems;
                }
              });
              if (isHaveItem) {
                let isDepartment = costCenterItem.costCenterOID === "00000000-0000-0000-0000-000000000000";
                return (
                  <InputGroup key={i} className="apportion-item-group">
                    <Popover content={costCenterItem.fieldName} placement="topLeft">
                      <Input
                        defaultValue={`${costCenterItem.fieldName}:`}
                        className="apportion-item-group-title"
                        disabled
                      />
                    </Popover>
                    {this.departmentCostCenterItem(record, index, costCenterItem, costCenterItemIndex, isDepartment)}
                  </InputGroup>
                );
              }
            })}
          </div>
        );
      case "amount":
        return readOnly ? (
          this.filterMoney(record.amount, currencyPrecision)
        ) : (
          <InputNumber
            className="apportion-amount"
            onChange={(value) => this.handleChangeAmount(value, index)}
            value={record.amount}
            precision={currencyPrecision}
            step={currencyPrecision ? 1 / Math.pow(10, currencyPrecision) : 1}
            formatter={(value) =>
              typeof value === "number" && !isNaN(value) ? Number(value.toFixed(currencyPrecision)) : value
            }
          />
        );
      case "proportion":
        return readOnly ? (
          `${(record.proportion * 100).toFixed(2)}%`
        ) : (
          <InputNumber
            min={0}
            className="expense-proportion-symbol"
            precision={2}
            step={0.01}
            max={100}
            onChange={(value) => this.handleChangeProportion(value, index)}
            value={record.proportion * 100}
            formatter={(value) => (typeof value === "number" && !isNaN(value) ? Number(value.toFixed(2)) : value)}
          />
        );
      case "companyRender":
        return !readOnly ? this.renderCompany(record, index) : record.apportionmentCompanyName;
      case "operate":
        return (
          <div className="apportion-operate">
            <If value={!readOnly}>
              <a onClick={() => this.handleCopyExpenseApportion(record)} style={{ marginRight: 10 }}>
                {messages("common.copy") /*复制*/}
              </a>
            </If>
            <If value={!readOnly && this.handleIsShowDelete()}>
              <a style={{ marginRight: 10 }} onClick={() => this.handleRemoveExpenseApportion(index)}>
                {messages("common.delete") /*删除*/}
              </a>
            </If>
          </div>
        );
      default:
        return null;
    }
  };

  ownIdentification = (companyOID) => {
    if (companyOID === configureStore.store.getState().login.user.companyOID) {
      return messages("common-1.key792") /*(我的)*/;
    }
    return "";
  };

  // 分摊公司选择控件处理
  renderCompany = (item, index) => {
    let setOfBooksId =
      this.safeGet(this.props.expenseInfo, "setOfBooksId") || this.safeGet(this.props.company, "setOfBooksId");
    let selectorItemCompany = {
      url: `${config.baseUrl}/api/widget/company/all?setOfBooksId=${setOfBooksId}&enabled=true&controlled=false&page=0&size=1000`,
      showSearchLabel: (record) =>
        !record.hasOwnProperty("companyOID") ? undefined : `${this.ownIdentification(record.companyOID)}${record.name}`,
      label: (record) => `${this.ownIdentification(record.companyOID)}${record.name}`,
      key: "companyOID",
      offlineSearchMode: true,
    };
    return (
      <Selector
        selectorItem={selectorItemCompany}
        onChange={(e) => {
          this.handleChangeCompany(index, e);
        }}
        entity={true}
        value={{ label: item.apportionmentCompanyName, key: item.apportionmentCompanyOID }}
        showSearch
        getPopupContainer={() => document.querySelector(".pre-payment-apportion")}
      />
    );
  };

  renderApportionBtn = () => {
    const apportionBtn = [
      {
        show: true,
        type: "div",
        params: {
          className: "new-expense-apportion",
          onClick: this.handleNewExpenseApportion,
        },
        child: <span>{messages("expense-1.key9") /*新建分摊*/}</span>,
      },
      {
        show: true,
        type: "div",
        params: {
          className: "new-expense-apportion",
          onClick: this.handleAverageExpenseApportion,
        },
        child: <span>{messages("expense-1.key10") /*一键均摊*/}</span>,
      },
    ];

    return (
      <Row className="button-row">
        {apportionBtn.map((item) => (
          <Col className="button-content">{React.createElement(item.type, item.params, item.child)}</Col>
        ))}
      </Row>
    );
  };

  // 新增分摊
  handleNewExpenseApportion = () => {
    let { expenseApportion, defaultExpenseApportion } = this.state;
    if (expenseApportion.length && expenseApportion.length === 100) {
      message.error(messages("finance-9.key171") /*分摊行最大数量为100*/);
      return -1;
    }
    const currencyPrecision = this.getCurrencyPrecision();
    const totalAmount = this.props.amount;
    let defaultExpense = deepFullCopy(defaultExpenseApportion);
    let accumulatorAmount = 0;
    expenseApportion.length &&
      (accumulatorAmount = expenseApportion
        .map((item) => Number(item.amount))
        .reduce((accumulator, currentValue) => accumulator + currentValue));
    let _amount = totalAmount - accumulatorAmount;
    defaultExpense.amount = _amount > 0 ? _amount.toFixed(currencyPrecision) : 0;
    defaultExpense.proportion =
      Math.abs(totalAmount) > Math.abs(accumulatorAmount) ? (defaultExpense.amount / totalAmount).toFixed(4) : 0;
    defaultExpense.defaultApportion = false;
    defaultExpense.costCenterItemDTOList.map((item) => {
      item.costCenterItemOID = null;
      item.departmentOid = null;
      item.costCenterItemName = null;
    });
    defaultExpense.apportionmentOID = null;
    defaultExpense.apportionmentLabels = [];
    defaultExpense.apportionmentCompanyOID = null;
    defaultExpense.apportionmentCompanyName = null;
    expenseApportion.push(defaultExpense);
    this.setState({ expenseApportion });
    this.props.onChange(expenseApportion);
  };

  // 一键均摊
  handleAverageExpenseApportion = () => {
    let { expenseApportion } = this.state;
    let { length } = expenseApportion;
    const currencyPrecision = this.getCurrencyPrecision() || 2;
    const totalAmount = this.props.amount;
    if (length === 0 || length === 1) {
      message.warning(messages("expense-1.key14") /*请先新增分摊行*/);
      return -1;
    }
    expenseApportion.map((item, index) => {
      if (index !== length - 1) {
        item.amount = (totalAmount / length).toFixed(currencyPrecision);
        item.proportion = (item.amount / totalAmount).toFixed(4);
      } else {
        // 最后一个分摊行补充金额 比率
        let otherApportions = expenseApportion.slice(0, index);
        item.amount = otherApportions
          .reduce((amount, currentValue) => {
            return amount - currentValue.amount;
          }, totalAmount)
          .toFixed(currencyPrecision);
        item.proportion = otherApportions.reduce((proportion, currentValue) => {
          return (proportion - currentValue.proportion).toFixed(4);
        }, 1);
      }
    });
    this.setState({ expenseApportion });
    this.props.onChange(expenseApportion);
  };

  departmentCostCenterItem = (record, index, constraint, costCenterIndex, isDepartment) => {
    const { expenseApportion } = this.state;
    const { company, options, readOnly, expenseInfo, jobInfo } = this.props;
    let { departmentOID } = jobInfo;
    let fatherHasValue = true;
    let departmentItem;
    let costCenterItems;
    if (isDepartment) {
      let departmentValue = {};
      record.costCenterItemDTOList.map((item) => {
        if (item.costCenterOID === constraint.costCenterOID) {
          departmentValue = item;
        }
      });
      departmentValue.departmentOid = departmentValue.costCenterItemOID;
      departmentValue.name = departmentValue.costCenterItemName;
      departmentValue.path = departmentValue.path || departmentValue.name;
      const name = departmentValue.costCenterItemName;
      let nameHtml = (
        <Popover placement="topLeft" content={name || ""}>
          {name || ""}
        </Popover>
      );
      let extraParams = {
        companyOID: record.companyOID || company.companyOID,
        leafEnable: !React.Component.prototype.checkFunctionProfiles("department.leaf.selection.required", [
          undefined,
          false,
        ]),
        needVirtual: false,
      };

      departmentItem = !readOnly ? (
        <Chooser
          type="department"
          valueKey="departmentOid"
          labelKey={options["department"]["fullPathDisabled"] === "false" ? "path" : "name"}
          className="department-select"
          single
          showClear
          itemMap
          onChange={(department) => this.handleChangeCostCenter(department, index, costCenterIndex)}
          value={departmentValue.costCenterItemOID ? [departmentValue] : []}
          listExtraParams={extraParams}
        />
      ) : (
        <Input prefix={nameHtml} style={{ borderLeft: "0px", width: "70%" }} disabled />
      );
    } else {
      let chooserItem = deepFullCopy(chooserData["expense_cost_center_item"]);
      chooserItem.key = "costCenterItemOID";
      chooserItem.title = constraint.fieldName;
      chooserItem.searchForm = [
        {
          type: "input",
          id: "keyword",
          label: `${constraint.fieldName}${messages("expense-1.key203") /*代码*/}/${
            messages("expense-1.key204") /*名称*/
          }`,
        },
      ];
      chooserItem.columns = [
        {
          title: `${constraint.fieldName}${messages("expense-1.key203") /*代码*/}`,
          dataIndex: "code",
        },
        {
          title: `${constraint.fieldName}${messages("expense-1.key204") /*名称*/}`,
          dataIndex: "name",
        },
      ];
      chooserItem.url = `${config.baseUrl}/api/my/cost/center/items/${constraint.costCenterOID}`;

      let _departmentOID = departmentOID;
      expenseApportion[index].costCenterItemDTOList.map((item) => {
        if (item.costCenterOID === "00000000-0000-0000-0000-000000000000") {
          _departmentOID = item.costCenterItemOID || departmentOID;
        }
      });
      let listExtraParams = {
        costCenterOID: constraint.costCenterOID,
        userOID: expenseInfo.ownerOID || expenseInfo.applicantOID,
        companyOID: record.apportionmentCompanyOID || record.companyOID, // 分摊公司
        departmentOID: _departmentOID, // 分摊部门
      };
      let value = {};
      record.costCenterItemDTOList.map((item) => {
        if (item.costCenterOID === constraint.costCenterOID) {
          value = item;
        }
      });
      if (value.type === "son") {
        //子成本中心取值依赖于已选的父成本中心OID
        record.costCenterItemDTOList.map((item) => {
          if (item.type === "father" && item.costCenterItemOID) {
            listExtraParams.parentCostCenterItemOID = item.costCenterItemOID;
          }
        });
      }
      value.name = value.costCenterItemName;
      const name = value.costCenterItemName;
      let nameHtml = (
        <Popover placement="topLeft" content={name || ""}>
          {name || ""}
        </Popover>
      );
      costCenterItems = !readOnly ? (
        <Chooser
          selectorItem={chooserItem}
          valueKey="costCenterItemOID"
          labelKey="name"
          single
          showClear
          itemMap
          listExtraParams={listExtraParams}
          disabled={value.type === "son" && !fatherHasValue} //父成本中心没有值时，子成本中心不可编辑
          onChange={(costCenterItem) => this.handleChangeCostCenter(costCenterItem, index, costCenterIndex)}
          value={value.costCenterItemOID ? [value] : []}
        />
      ) : (
        <Input prefix={nameHtml} style={{ borderLeft: "0px", width: "70%" }} disabled />
      );
    }
    return isDepartment ? departmentItem : costCenterItems;
  };

  handleChangeCostCenter = (result, index, costCenterIndex, companyChange = false) => {
    const { options } = this.props;
    if (result) {
      if (result.length === 0) {
        result[0] = {};
      }
      let { expenseApportion } = this.state;
      let costCenterItemDTOList = expenseApportion[index].costCenterItemDTOList[costCenterIndex];
      if (
        companyChange ||
        (costCenterItemDTOList &&
          (costCenterItemDTOList.costCenterItemOID !== result[0].costCenterItemOID ||
            costCenterItemDTOList.costCenterItemOID !== result[0].departmentOid))
      ) {
        let name = result[0].name;
        if (costCenterItemDTOList.costCenterOID === "00000000-0000-0000-0000-000000000000") {
          result[0].costCenterItemOID = result[0].departmentOid;
          if (options["department"]["fullPathDisabled"] === "false") {
            name = result[0].path || result[0].name;
          }
        }
        if (
          costCenterItemDTOList.type === "father" &&
          result[0].costCenterItemOID !== costCenterItemDTOList.costCenterItemOID
        ) {
          //父成本中心
          //如果修改父成本中心项，则子成本中心清空
          expenseApportion[index].costCenterItemDTOList.map((item) => {
            if (item.type === "son") {
              item.costCenterItemOID = "";
            }
          });
        }
        costCenterItemDTOList.costCenterItemOID = result[0].costCenterItemOID;
        costCenterItemDTOList.costCenterItemName = name;
        costCenterItemDTOList.name = name;
        costCenterItemDTOList.itemCode = result[0].custDeptNumber || result[0].code;
        expenseApportion[index].costCenterItemDTOList[costCenterIndex] = costCenterItemDTOList;
        this.setState({ expenseApportion });
        this.props.onChange(expenseApportion);
      }
    }
  };

  // 选择分摊公司
  handleChangeCompany = (index, company) => {
    let { expenseApportion } = this.state;
    const { expenseInfo } = this.props;
    let currentApportion = expenseApportion[index];
    currentApportion.apportionmentCompanyOID = this.safeGet(company, "companyOID");
    currentApportion.apportionmentCompanyName = this.safeGet(company, "name");
    this.props.onChange(expenseApportion);
    this.setState({ expenseApportion }, async () => {
      let costCenterItemDTOList = currentApportion.costCenterItemDTOList;
      // 部门控件
      let departmentField = costCenterItemDTOList.find(
        (item) => item.costCenterOID === "00000000-0000-0000-0000-000000000000"
      );
      let departmentIndex = costCenterItemDTOList.indexOf(departmentField);
      let departmentInfo = {
        name: "",
        departmentOid: "",
        code: "",
      };
      if (departmentField && departmentField.costCenterItemOID) {
        try {
          const companyOID =
            currentApportion.apportionmentCompanyOID ||
            expenseInfo.docCompanyOID ||
            expenseInfo.companyOID ||
            this.props.company.companyOID;
          let res = await baseService.checkDepartmentNeedEmpty({
            companyOID: companyOID,
            departmentOID: departmentField.costCenterItemOID,
          });
          if (this.safeGet(res.data, "association") === "Y") {
            departmentInfo = {
              name: departmentField.costCenterItemName,
              code: departmentField.itemCode,
              departmentOid: departmentField.costCenterItemOID,
            };
          }
        } catch (e) {}
      }
      this.handleChangeCostCenter([departmentInfo], index, departmentIndex, true);
    });
  };

  handleChangeAmount = (value, index) => {
    if (typeof value === "number" && !isNaN(value) && value !== 0) {
      let { expenseApportion } = this.state;
      let currencyPrecision = this.getCurrencyPrecision();
      let amount = Number(this.props.amount);
      expenseApportion[index].amount = Number(value.toFixed(currencyPrecision));
      expenseApportion[index].proportion = value / amount > 1 ? 1 : value / amount;
      this.setState({ expenseApportion });
      this.props.onChange(expenseApportion);
    }
  };

  handleChangeProportion = (value, index) => {
    if (typeof value === "number" && !isNaN(value)) {
      let { expenseApportion } = this.state;
      let amount = Number(this.props.amount);
      let currencyPrecision = this.getCurrencyPrecision();
      expenseApportion[index].proportion = value / 100;
      expenseApportion[index].amount = Number(((value / 100) * amount).toFixed(currencyPrecision));
      this.setState({ expenseApportion });
      this.props.onChange(expenseApportion);
    }
  };

  handleCopyExpenseApportion = (record) => {
    let { expenseApportion } = this.state;
    if (expenseApportion.length && expenseApportion.length === 100) {
      message.error(messages("finance-9.key171") /*分摊行最大数量为100*/);
      return -1;
    }
    let target = JSON.parse(JSON.stringify(record));
    target.amount = 0;
    target.proportion = 0;
    target.apportionmentOID = null;
    target.defaultApportion = false;
    target.apportionmentOID = null;
    target.apportionmentLabels = [];
    expenseApportion.push(target);
    this.setState({ expenseApportion });
    this.props.onChange(expenseApportion);
  };

  handleIsShowDelete = () => {
    const {
      expenseApportion: { length },
      defaultExpenseApportion,
    } = this.state;
    return !(length === 1 && defaultExpenseApportion && defaultExpenseApportion.applicationApportionmentId);
  };

  handleRemoveExpenseApportion = (index) => {
    let { expenseApportion } = this.state;
    if (index === 0 && expenseApportion.length > 1) {
      expenseApportion[1].defaultApportion = true;
      this.setState({ defaultExpenseApportion: expenseApportion[1] });
    }
    expenseApportion.splice(index, 1);
    this.setState({ expenseApportion });
    this.props.onChange(expenseApportion);
  };

  render() {
    const { columns, expenseApportion } = this.state;
    const { readOnly } = this.props;
    return (
      <div className="pre-payment-apportion">
        <ResizeTable
          showUtils
          tableName="expense-apportion-table"
          columns={columns}
          dataSource={expenseApportion}
          bordered
          pagination={false}
        />
        {!readOnly && this.renderApportionBtn()}
      </div>
    );
  }
}

PrePaymentApportion.propTypes = {
  readOnly: React.PropTypes.bool,
  departmentOID: React.PropTypes.string,
  onChange: React.PropTypes.func,
  expenseInfo: React.PropTypes.object,
  jobInfo: React.PropTypes.object,
  amount: React.PropTypes.number, // 分摊金额
  apportionValue: React.PropTypes.array, //分摊项信息
};

function mapStateToProps(state) {
  return {
    company: state.login.company,
    options: state.login.options,
  };
}

export default connect(mapStateToProps)(PrePaymentApportion);
